/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <GLES3/gl3.h>
#include <string>
#include <napi/native_api.h>

#ifndef XComponent_common_H
#define XComponent_common_H

/**
 * Vertex shader.
 */
#define SHADER(s) #s
const char NEURON_VERTEX_SHADER[]= SHADER(#version 300 es\n
layout(location = 0) in vec3 a_position;
uniform vec4 a_color;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec4 v_color;
void main()
{
   gl_Position = projection*view*model*vec4(a_position,1.0f); 
   v_color = a_color; 
}
);
const char NEURON_FRAGMENT_SHADER[] = SHADER(#version 300 es\n
                                      precision mediump float;                 
                                      in vec4 v_color;  
                                      out vec4 fragColor; 
                                      void main()
                                      {
                                      fragColor=vec4(v_color.xyz,1.0);
                                      }
);

const char VERTEX_SHADER[] = SHADER(#version 300 es\n
                             layout(location = 0) in vec3 a_position;
                             layout(location = 1) in vec4 a_color;
                             layout(location=2) in vec3 normal; 
                             out vec4 v_color; 
                             out vec3 tnorm;
                             out vec3 view_direction;
                             uniform mat4 model;
                             uniform mat4 view;
                             uniform mat4 projection;
                             void main() 
                             {
                                gl_Position = projection*view*model*vec4(a_position,1.0f); 
                             vec4 pos_in_camera = view*model * vec4(a_position, 1.0);
                                v_color = a_color;
                             tnorm = normalize((view*model*vec4(normal.xyz, 0.0)).xyz);
                             view_direction = normalize(pos_in_camera.xyz);
                             } 
);

/**
 * Fragment shader.
 */
const char FRAGMENT_SHADER[] = SHADER(#version 300 es\n
                               precision mediump float;                  
                               in vec4 v_color;                          
                               in vec3 tnorm;
                               in vec3 view_direction;
                               out vec4 fragColor;                       
                               void main()                               
                               {                                   
                               float edginess = 1.0 - abs(dot(tnorm, view_direction));
                               float opacity = clamp(edginess - 0.30, 0.0, 0.5);
                               // Darken compartment at the very edge\n
                               float blackness = pow(edginess, 4.0) - 0.3;
                               vec3 c = mix(v_color.xyz*1.2, vec3(0, 0, 0), blackness);
                                  fragColor = vec4(c,opacity); 
                               }
);

const char SOMA_FRAGMENT_SHADER[]=SHADER(#version 300 es\n
precision highp float;
in vec4 color;
in vec3 light;
in vec4 position;
out vec4 fColor;

void main(void) {
	vec3 norm = normalize(cross(dFdx(position.xyz), dFdy(position.xyz)));
	float diffuse = max(dot(light, norm.xyz), 0.0);
    float spec = pow(max(dot(light, norm.xyz), 0.0), 50.0f);
	fColor = color*(0.7 + 0.8*diffuse)+spec*vec4(1.0,1.0,1.0,1.0);
}
);

const char SOMA_VERTEX_SHADER[]=SHADER(#version 300 es\n
precision highp float;
    layout( location = 0) in vec3 a_position;
	uniform vec4 a_color;
	uniform vec4 a_center;
    uniform float scale;
	uniform mat4 model;
	uniform mat4 view;
	uniform mat4 projection;

	out vec4 color;
	out vec4 position;
	out vec3 light;
	void main(void) {
		light = normalize(inverse(view*model)*vec4(0.0, 0.0, 1.0, 0.0)).xyz;

		position = vec4(a_position.xyz*scale, 1.0) + vec4(a_center.xyz, 0.0);
		gl_Position = projection*view*model*position;
        color = a_color;
	}
);
/**
 * Background color #182431.
 */
const GLfloat BACKGROUND_COLOR[] = {24.0f / 255, 36.0f / 255, 149.0f / 255, 1.0f};

/**
 * Draw color #7E8FFB.
 */
const GLfloat DRAW_COLOR[] = {255.0f / 255, 255.0f / 255, 255.0f / 255, 1.0f};

/**
 * Change color #92D6CC.
 */
const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f};

/**
 * Background area.
 */
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {-1.0f, 0.5f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f};

/**
 * Log print domain.
 */
const unsigned int LOG_PRINT_DOMAIN = 0xFF00;

/**
 * Get context parameter count.
 */
const size_t GET_CONTEXT_PARAM_CNT = 1;

/**
 * Fifty percent.
 */
const float FIFTY_PERCENT = 0.5;

/**
 * Pointer size.
 */
const GLint POINTER_SIZE = 2;

/**
 * Triangle fan size.
 */
const GLsizei TRIANGLE_FAN_SIZE = 4;

/**
 * Egl red size default.
 */
const int EGL_RED_SIZE_DEFAULT = 8;

/**
 * Egl green size default.
 */
const int EGL_GREEN_SIZE_DEFAULT = 8;

/**
 * Egl blue size default.
 */
const int EGL_BLUE_SIZE_DEFAULT = 8;

/**
 * Egl alpha size default.
 */
const int EGL_ALPHA_SIZE_DEFAULT = 8;

/**
 * Default x position.
 */
const int DEFAULT_X_POSITION = 0;

/**
 * Default y position.
 */
const int DEFAULT_Y_POSITION = 0;

/**
 * Gl red default.
 */
const GLfloat GL_RED_DEFAULT = 0.0;

/**
 * Gl green default.
 */
const GLfloat GL_GREEN_DEFAULT = 0.0;

/**
 * Gl blue default.
 */
const GLfloat GL_BLUE_DEFAULT = 0.0;

/**
 * Gl alpha default.
 */
const GLfloat GL_ALPHA_DEFAULT = 1.0;

/**
 * Program error.
 */
const GLuint PROGRAM_ERROR = 0;

/**
 * Rectangle vertices size.
 */
const int RECTANGLE_VERTICES_SIZE = 8;

/**
 * Position handle name.
 */
const char POSITION_NAME[] = "a_position";

/**
 * Position error.
 */
const GLint POSITION_ERROR = -1;

/**
 * Context type.
 */
enum ContextType {
    APP_LIFECYCLE,
    PAGE_LIFECYCLE,
};

/**
 * Config attribute list.
 */
const EGLint ATTRIB_LIST[] = {
    // Key,value.
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT, EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT,
    EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT, EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT,EGL_DEPTH_SIZE,24, EGL_RENDERABLE_TYPE,
    EGL_OPENGL_ES2_BIT,
    // End.
    EGL_NONE};

/**
 * Context attributes.
 */
const EGLint CONTEXT_ATTRIBS[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
#endif // XComponent_common_H